<script setup>
import {computed, reactive, ref} from 'vue'
import {ElMessage} from 'element-plus'

import {saveImageSrcUrlList} from '@/api/ImageSrcUrl.js'

import axios from 'axios'
import * as cheerio from 'cheerio'

const formData = reactive({
  url: '/everia/',
  page: '1',
  param: '',
  lambda: '.thumbnail a',
  type: '',
  isEnableCategory: false,
  categoryUrl: 'category/japan/',
})

const params = [
  {
    label: 'japan',
    value: 'category/japan/',
    title: '日本'
  },
    {
    label: 'china',
    value: 'category/chinese/',
    title: '中国'
  },
    {
    label: 'korean',
    value: 'category/korea/',
      title: '韩国'
  },
    {
    label: 'gravure',
    value: 'category/gravure/',
      title: ' gravure'
  },
    {
    label: 'cosplay',
    value: 'category/cosplay/',
      title: 'Cosplay'
  },
    {
    label: 'thailand',
    value: 'category/thailand/',
      title: '泰国'
  },
]


// 添加URL预览计算属性
const previewUrl = computed(() => {
  // 校验 page 是否为有效数字
  const pageNum = parseInt(formData.page, 10)

  // 构建基础 URL
  let baseUrl
  try {
    baseUrl = new URL(formData.url.startsWith('http') ? formData.url : `http://${formData.url}`)
  } catch (e) {
    console.error('Invalid URL:', formData.url)
    return ''
  }


  if (formData.isEnableCategory){
    baseUrl.href = baseUrl.href + formData.categoryUrl
  }else{
    baseUrl.pathname = baseUrl.pathname.replace(/\/$/, '')
    baseUrl.search = formData.param ? `?s=${formData.param}` : ''
  }
  // 处理 page：当页码大于等于2时才添加页码路径
  if (pageNum >= 2) {
    baseUrl.pathname = baseUrl.pathname + pageNum
  }
  return baseUrl.toString()
})


const loading = ref(false)

//确认获取到链接
const handleGetLinks = ref(false)
const progress = ref(0)
const selectedImages = ref([])
const pageSource = ref('')
const showSource = ref(false)
const thumbnailLinks = ref([])


// 添加分页相关的状态变量
const currentPage = ref(1)
const pageSize = ref(10)

// 计算当前页的标签
const paginatedTags = computed(() => {
  const start = (currentPage.value - 1) * pageSize.value
  const end = start + pageSize.value
  return thumbnailLinks.value.slice(start, end)
})

// 计算总页数
const totalPages = computed(() => {
  return Math.ceil(thumbnailLinks.value.length / pageSize.value)
})

// 处理页码变化
const handlePageChange = (page) => {
  currentPage.value = page
}

// 添加选择器示例
const selectorExamples = [
  {
    label: '基础选择器', examples: [
      {value: 'img', description: '选择所有图片'},
      {value: 'figure img', description: '选择 figure 标签内的图片'},
      {value: '.gallery img', description: '选择 class 为 gallery 的元素内的图片'},
      {value: '#main img', description: '选择 id 为 main 的元素内的图片'}
    ]
  },
  {
    label: '属性选择器', examples: [
      {value: 'img[src*=".jpg"]', description: '选择 src 属性包含 .jpg 的图片'},
      {value: 'img[alt]', description: '选择带有 alt 属性的图片'},
      {value: 'img[width="800"]', description: '选择宽度为 800 的图片'}
    ]
  },
  {
    label: '组合选择器', examples: [
      {value: 'figure.gallery img', description: '选择 class 为 gallery 的 figure 标签内的图片'},
      {value: 'div.content img[src*=".png"]', description: '选择 class 为 content 的 div 内的 PNG 图片'}
    ]
  }
]

// 添加选择器语法提示
const selectorTips = [
  '使用空格分隔表示层级关系，如：figure img',
  '使用 . 表示 class，如：.gallery',
  '使用 # 表示 id，如：#main',
  '使用 [] 表示属性选择，如：[src*=".jpg"]',
  '使用 * 表示包含，如：[src*=".jpg"]',
  '使用 = 表示等于，如：[width="800"]'
]


// 添加分页范围
const pageRange = ref({
  start: 1,
  end: 5
})

// 统一获取缩略图链接的方法
const fetchThumbnailLinks = async (isBatch = false) => {
  try {
    loading.value = true;

    // 初始化缩略图链接数组
    if (!isBatch) {
      thumbnailLinks.value = [];
    }

    // 输入验证
    validateInputs();

    // 准备要处理的页面数组
    const pages = preparePages(isBatch);

    // 并发处理页面
    await processPagesConcurrently(pages);

    // 处理结果
    handleResults();
  } catch (error) {
    handleError(error);
  } finally {
    loading.value = false;
  }
};

// 输入验证函数
const validateInputs = () => {
  if (!formData.url || typeof formData.url !== 'string') {
    throw new Error('无效的URL');
  }
  if (formData.param && typeof formData.param !== 'string') {
    throw new Error('无效的参数');
  }
};

// 准备要处理的页面数组
const preparePages = (isBatch) => {
  return isBatch
      ? Array.from(
          { length: pageRange.value.end - pageRange.value.start + 1 },
          (_, i) => pageRange.value.start + i
      )
      : [formData.page];
};

// 并发处理页面
const processPagesConcurrently = async (pages) => {
  const MAX_CONCURRENT_REQUESTS = 5;
  const requestChunks = [];

  // 将请求分块
  for (let i = 0; i < pages.length; i += MAX_CONCURRENT_REQUESTS) {
    requestChunks.push(pages.slice(i, i + MAX_CONCURRENT_REQUESTS));
  }

  // 按块处理请求
  for (const chunk of requestChunks) {
    await Promise.all(chunk.map(processSinglePage));
  }
};

// 处理单个页面
const processSinglePage = async (page) => {
  try {
    const currentPage = (Number(page) === 1) ? '' : `page/${page}/`;
    const param = formData.param && !formData.isEnableCategory
        ? `?s=${encodeURIComponent(formData.param)}`
        : '';
    const url = formData.url + (formData.isEnableCategory ? formData.categoryUrl : "");

    console.log(`${formData.url}, ${currentPage}, ${param}, ${url}`);

    const response = await axios.get(url + currentPage + param, {
      timeout: 300000
    });

    const $ = cheerio.load(response.data);
    const links = extractLinks($, page);

    if (links.length === 0) {
      ElMessage.warning(`第 ${page} 页未找到任何链接`);
    } else {
      console.log(`第 ${page} 页获取成功，共 ${links.length} 个链接`);
      thumbnailLinks.value.push(...links);
      ElMessage.success(`第 ${page} 页获取成功，共 ${links.length} 个链接`);
      handleGetLinks.value = true;
    }
  } catch (error) {
    console.error(`获取第 ${page} 页链接失败:`, error);
    ElMessage.error(`获取第 ${page} 页链接失败：${error.message}`);
  }
};

// 从页面中提取链接
const extractLinks = ($, page) => {
  return $(formData.lambda)
      .map((_, a) => {
        const $a = $(a);
        const $img = $a.find('img');
        return {
          href: $a.attr('href'),
          src: $img.attr('src'),
          alt: $img.attr('alt') || '无描述',
          page: page
        };
      })
      .get();
};

// 处理最终结果
const handleResults = () => {
  const totalLinks = thumbnailLinks.value.length;
  if (totalLinks === 0) {
    ElMessage.warning('未找到任何链接');
  }
};

// 错误处理
const handleError = (error) => {
  console.error('获取链接失败:', error);
  const errorMessage = typeof error.response?.data === 'object'
      ? JSON.stringify(error.response.data)
      : error.response?.data || error.message;
  ElMessage.error('获取链接失败：' + errorMessage);
};
const saveThumbnailLinks = async () => {
  console.log(thumbnailLinks.value)

  const res = await saveImageSrcUrlList(thumbnailLinks.value)
  console.log("res:" + res + ",data:" + res.data)
  if (res.code === 200) {
    ElMessage.success(res.message)
  } else {
    ElMessage.error(res.message)
  }
}

const initThumbnailLinks = () => {
  thumbnailLinks.value = [];
  loading.value = false
}

</script>
<template>
  <div class="image-list-crawler">
    <el-card class="form-card">
      <template #header>
        <div class="card-header">
          <span>图片爬虫配置</span>
        </div>
      </template>

      <el-form :model="formData" label-width="80px">
        <el-row :gutter="20">
          <el-col :span="8">
            <el-form-item label="基础URL">
              <el-input v-model="formData.url" placeholder="请输入基础URL">
                <template #prepend>http://</template>
              </el-input>
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="分页参数">
              <el-input v-model="formData.page" placeholder="请输入分页参数">
                <template #prepend>page/</template>
                <template #append>/</template>
              </el-input>
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item v-if="!formData.isEnableCategory" label="URL参数">
              <el-input v-model="formData.param" placeholder="请输入URL参数">
                <template #prepend>?s=</template>
              </el-input>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="8">
            <el-form-item label="是否启用类别查询">
              <el-radio-group v-model="formData.isEnableCategory">
                <el-radio :value= false size="large">关闭</el-radio>
                <el-radio :value= true size="large">开启</el-radio>
              </el-radio-group>
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="类别">
              <el-select v-model="formData.categoryUrl" clearable placeholder="类型" style="width: 120px;">
                <el-option
                    v-for="item in params"
                    :key="item.value"
                    :label="item.title"
                    :value="item.value"
                />
              </el-select>
            </el-form-item>
          </el-col>

        </el-row>

        <el-form-item label="URL预览">
          <el-input v-model="previewUrl" readonly>
            <template #append>
              <el-button @click="window.open(previewUrl, '_blank')">
                打开链接
              </el-button>
            </template>
          </el-input>
        </el-form-item>

        <el-form-item label="分页范围">
          <el-row :gutter="20">
            <el-col :span="11">
              <el-input-number
                  v-model="pageRange.start"
                  :min="1"
                  :max="pageRange.end"
                  placeholder="起始页"
              />
            </el-col>
            <el-col :span="2" class="text-center">
              <span>至</span>
            </el-col>
            <el-col :span="11">
              <el-input-number
                  v-model="pageRange.end"
                  :min="pageRange.start"
                  placeholder="结束页"
              />
            </el-col>
          </el-row>
        </el-form-item>

        <el-form-item label="选择器">
          <el-input v-model="formData.lambda" placeholder="请输入CSS选择器">
            <template #append>
              <el-popover placement="right" :width="400" trigger="click">
                <template #reference>
                  <el-button>选择器帮助</el-button>
                </template>
                <div class="selector-help">
                  <div v-for="(category, index) in selectorExamples" :key="index">
                    <h4>{{ category.label }}</h4>
                    <el-descriptions :column="1" border>
                      <el-descriptions-item v-for="(example, idx) in category.examples" :key="idx">
                        <div class="selector-example">
                          <code>{{ example.value }}</code>
                          <span>{{ example.description }}</span>
                        </div>
                      </el-descriptions-item>
                    </el-descriptions>
                  </div>
                </div>
              </el-popover>
            </template>
          </el-input>
        </el-form-item>


        <el-form-item>
          <el-button type="success" @click="fetchThumbnailLinks(false)" :loading="loading">
            获取单页链接
          </el-button>
          <el-button type="primary" @click="fetchThumbnailLinks(true)" :loading="loading">
            批量获取链接
          </el-button>
          <el-button type="danger" @click="loading = false"> 取消</el-button>
          <el-button type="warning" v-if="handleGetLinks" @click="saveThumbnailLinks()">保存链接</el-button>
          <el-button type="warning" v-if="handleGetLinks" @click="initThumbnailLinks()">清空图片链接</el-button>
        </el-form-item>
      </el-form>
    </el-card>

    <el-card v-if="thumbnailLinks.length > 0" class="result-card">
      <template #header>
        <div class="card-header">
          <span>缩略图链接列表</span>
          <span class="link-count">共 {{ thumbnailLinks.length }} 个链接</span>
        </div>
      </template>

      <el-table :data="paginatedTags">
        <el-table-column prop="page" label="页码"/>
        <el-table-column prop="alt" label="链接文本" width="300">
          <template #default="{ row }">
            <span>{{ row.alt || '无文本' }}</span>
          </template>
        </el-table-column>
        <el-table-column prop="href" label="链接地址">
          <template #default="{ row }">
            {{ row.href || '无链接' }}
          </template>
        </el-table-column>
        <el-table-column label="图片">
          <template #default="{ row }">
            <div style="position: relative; display: inline-block;">
              <el-image
                  :src="row.src || ''"
                  fit="cover"
                  style="width: 158px; height: 237px"
              />
              <div class="image-info">
                <p>{{ row.alt || '无描述' }}</p>
              </div>
            </div>
          </template>
        </el-table-column>
        <el-table-column label="操作" width="120">
          <template #default="{ row }">
            <el-button
                type="primary"
                size="small"
                @click="window.open(row.href, '_blank')"
                :disabled="!row.href"
            >
              访问链接
            </el-button>
          </template>
        </el-table-column>
      </el-table>

      <div class="pagination-container">
        <el-pagination
            layout="prev, pager, next"
            :total="thumbnailLinks.length"
            :page-size="pageSize"
            :current-page="currentPage"
            @current-change="handlePageChange"
        />
      </div>

      <!-- 新增保存图片地址按钮 -->
      <div class="save-button-container">
        <el-button
            type="success"
            @click="saveThumbnailLinks"
            :loading="loading"
        >
          保存图片地址列表
        </el-button>
      </div>
    </el-card>

  </div>
</template>

<style scoped>
.image-list-crawler {
  padding: 20px;
  width: 100%;
  margin: 0 auto;
}

.form-card {
  margin-bottom: 20px;
}

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.selector-help {
  max-height: 400px;
  overflow-y: auto;
}

.selector-example {
  display: flex;
  align-items: center;
  gap: 10px;
}

.selector-example code {
  background-color: #f5f7fa;
  padding: 2px 6px;
  border-radius: 4px;
  font-family: monospace;
}

.image-info {
  padding: 8px;
  background: rgba(0, 0, 0, 0.7);
  color: white;
  font-size: 12px;
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  opacity: 0.8;
  transition: opacity 0.3s;
}

.image-info:hover {
  opacity: 1;
}

.image-actions {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  padding: 10px;
  background: rgba(243, 243, 248, 0.5);
  display: flex;
  justify-content: space-between;
  align-items: center;
  opacity: 1;
  /* 修改为默认显示 */

  .el-checkbox {
    margin-right: 8px;
  }
}

.attribute-actions {
  margin-top: 8px;
  text-align: right;
}

.result-card {
  margin-top: 20px;
}

.link-count,
.image-count {
  font-size: 14px;
  color: #909399;
}

:deep(.el-descriptions__label) {
  width: 100px;
}

:deep(.el-descriptions__content) {
  word-break: break-all;
}

.text-center {
  text-align: center;
  line-height: 32px;
}

:deep(.el-input-number) {
  width: 100%;
}

.pagination-container {
  margin-top: 20px;
  display: flex;
  justify-content: center;
}

/* 新增保存按钮样式 */
.save-button-container {
  margin-top: 20px;
  display: flex;
  justify-content: center;
  padding: 20px 0;
  border-top: 1px solid var(--el-border-color-light);
}
</style>